/* crypto.c */

/********************/
/* CRYPTO-ROUTINES  */
/* for Secure Phone */
/* (C) 2003 by NAH6 */
/********************/

/*------------*/
/*  INCLUDES  */
/*------------*/

#include "crypto.h"

/*--------------*/
/*  PROTOTYPES  */
/*--------------*/

static void crypto_sha__compress (struct crypto_sha_state *state);

/*--------------*/
/*  KONSTANTEN  */
/*--------------*/

static const unsigned char crypto_aes_sbox0[256] =
{
  0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
  0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
  0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
  0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
  0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
  0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
  0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
  0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
  0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
  0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
  0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
  0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
  0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
  0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
  0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
  0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
  0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
  0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
  0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
  0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
  0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
  0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
  0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
  0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
  0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
  0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
  0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
  0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
  0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
  0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
  0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
  0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};

/*--*/

static const unsigned long crypto_aes_sbox1[256] =
{
  0xA56363C6L, 0x847C7CF8L, 0x997777EEL, 0x8D7B7BF6L,
  0x0DF2F2FFL, 0xBD6B6BD6L, 0xB16F6FDEL, 0x54C5C591L,
  0x50303060L, 0x03010102L, 0xA96767CEL, 0x7D2B2B56L,
  0x19FEFEE7L, 0x62D7D7B5L, 0xE6ABAB4DL, 0x9A7676ECL,
  0x45CACA8FL, 0x9D82821FL, 0x40C9C989L, 0x877D7DFAL,
  0x15FAFAEFL, 0xEB5959B2L, 0xC947478EL, 0x0BF0F0FBL,
  0xECADAD41L, 0x67D4D4B3L, 0xFDA2A25FL, 0xEAAFAF45L,
  0xBF9C9C23L, 0xF7A4A453L, 0x967272E4L, 0x5BC0C09BL,
  0xC2B7B775L, 0x1CFDFDE1L, 0xAE93933DL, 0x6A26264CL,
  0x5A36366CL, 0x413F3F7EL, 0x02F7F7F5L, 0x4FCCCC83L,
  0x5C343468L, 0xF4A5A551L, 0x34E5E5D1L, 0x08F1F1F9L,
  0x937171E2L, 0x73D8D8ABL, 0x53313162L, 0x3F15152AL,
  0x0C040408L, 0x52C7C795L, 0x65232346L, 0x5EC3C39DL,
  0x28181830L, 0xA1969637L, 0x0F05050AL, 0xB59A9A2FL,
  0x0907070EL, 0x36121224L, 0x9B80801BL, 0x3DE2E2DFL,
  0x26EBEBCDL, 0x6927274EL, 0xCDB2B27FL, 0x9F7575EAL,
  0x1B090912L, 0x9E83831DL, 0x742C2C58L, 0x2E1A1A34L,
  0x2D1B1B36L, 0xB26E6EDCL, 0xEE5A5AB4L, 0xFBA0A05BL,
  0xF65252A4L, 0x4D3B3B76L, 0x61D6D6B7L, 0xCEB3B37DL,
  0x7B292952L, 0x3EE3E3DDL, 0x712F2F5EL, 0x97848413L,
  0xF55353A6L, 0x68D1D1B9L, 0x00000000L, 0x2CEDEDC1L,
  0x60202040L, 0x1FFCFCE3L, 0xC8B1B179L, 0xED5B5BB6L,
  0xBE6A6AD4L, 0x46CBCB8DL, 0xD9BEBE67L, 0x4B393972L,
  0xDE4A4A94L, 0xD44C4C98L, 0xE85858B0L, 0x4ACFCF85L,
  0x6BD0D0BBL, 0x2AEFEFC5L, 0xE5AAAA4FL, 0x16FBFBEDL,
  0xC5434386L, 0xD74D4D9AL, 0x55333366L, 0x94858511L,
  0xCF45458AL, 0x10F9F9E9L, 0x06020204L, 0x817F7FFEL,
  0xF05050A0L, 0x443C3C78L, 0xBA9F9F25L, 0xE3A8A84BL,
  0xF35151A2L, 0xFEA3A35DL, 0xC0404080L, 0x8A8F8F05L,
  0xAD92923FL, 0xBC9D9D21L, 0x48383870L, 0x04F5F5F1L,
  0xDFBCBC63L, 0xC1B6B677L, 0x75DADAAFL, 0x63212142L,
  0x30101020L, 0x1AFFFFE5L, 0x0EF3F3FDL, 0x6DD2D2BFL,
  0x4CCDCD81L, 0x140C0C18L, 0x35131326L, 0x2FECECC3L,
  0xE15F5FBEL, 0xA2979735L, 0xCC444488L, 0x3917172EL,
  0x57C4C493L, 0xF2A7A755L, 0x827E7EFCL, 0x473D3D7AL,
  0xAC6464C8L, 0xE75D5DBAL, 0x2B191932L, 0x957373E6L,
  0xA06060C0L, 0x98818119L, 0xD14F4F9EL, 0x7FDCDCA3L,
  0x66222244L, 0x7E2A2A54L, 0xAB90903BL, 0x8388880BL,
  0xCA46468CL, 0x29EEEEC7L, 0xD3B8B86BL, 0x3C141428L,
  0x79DEDEA7L, 0xE25E5EBCL, 0x1D0B0B16L, 0x76DBDBADL,
  0x3BE0E0DBL, 0x56323264L, 0x4E3A3A74L, 0x1E0A0A14L,
  0xDB494992L, 0x0A06060CL, 0x6C242448L, 0xE45C5CB8L,
  0x5DC2C29FL, 0x6ED3D3BDL, 0xEFACAC43L, 0xA66262C4L,
  0xA8919139L, 0xA4959531L, 0x37E4E4D3L, 0x8B7979F2L,
  0x32E7E7D5L, 0x43C8C88BL, 0x5937376EL, 0xB76D6DDAL,
  0x8C8D8D01L, 0x64D5D5B1L, 0xD24E4E9CL, 0xE0A9A949L,
  0xB46C6CD8L, 0xFA5656ACL, 0x07F4F4F3L, 0x25EAEACFL,
  0xAF6565CAL, 0x8E7A7AF4L, 0xE9AEAE47L, 0x18080810L,
  0xD5BABA6FL, 0x887878F0L, 0x6F25254AL, 0x722E2E5CL,
  0x241C1C38L, 0xF1A6A657L, 0xC7B4B473L, 0x51C6C697L,
  0x23E8E8CBL, 0x7CDDDDA1L, 0x9C7474E8L, 0x211F1F3EL,
  0xDD4B4B96L, 0xDCBDBD61L, 0x868B8B0DL, 0x858A8A0FL,
  0x907070E0L, 0x423E3E7CL, 0xC4B5B571L, 0xAA6666CCL,
  0xD8484890L, 0x05030306L, 0x01F6F6F7L, 0x120E0E1CL,
  0xA36161C2L, 0x5F35356AL, 0xF95757AEL, 0xD0B9B969L,
  0x91868617L, 0x58C1C199L, 0x271D1D3AL, 0xB99E9E27L,
  0x38E1E1D9L, 0x13F8F8EBL, 0xB398982BL, 0x33111122L,
  0xBB6969D2L, 0x70D9D9A9L, 0x898E8E07L, 0xA7949433L,
  0xB69B9B2DL, 0x221E1E3CL, 0x92878715L, 0x20E9E9C9L,
  0x49CECE87L, 0xFF5555AAL, 0x78282850L, 0x7ADFDFA5L,
  0x8F8C8C03L, 0xF8A1A159L, 0x80898909L, 0x170D0D1AL,
  0xDABFBF65L, 0x31E6E6D7L, 0xC6424284L, 0xB86868D0L,
  0xC3414182L, 0xB0999929L, 0x772D2D5AL, 0x110F0F1EL,
  0xCBB0B07BL, 0xFC5454A8L, 0xD6BBBB6DL, 0x3A16162CL
};

static const unsigned long crypto_aes_sbox2[256] =
{
  0x6363C6A5L, 0x7C7CF884L, 0x7777EE99L, 0x7B7BF68DL,
  0xF2F2FF0DL, 0x6B6BD6BDL, 0x6F6FDEB1L, 0xC5C59154L,
  0x30306050L, 0x01010203L, 0x6767CEA9L, 0x2B2B567DL,
  0xFEFEE719L, 0xD7D7B562L, 0xABAB4DE6L, 0x7676EC9AL,
  0xCACA8F45L, 0x82821F9DL, 0xC9C98940L, 0x7D7DFA87L,
  0xFAFAEF15L, 0x5959B2EBL, 0x47478EC9L, 0xF0F0FB0BL,
  0xADAD41ECL, 0xD4D4B367L, 0xA2A25FFDL, 0xAFAF45EAL,
  0x9C9C23BFL, 0xA4A453F7L, 0x7272E496L, 0xC0C09B5BL,
  0xB7B775C2L, 0xFDFDE11CL, 0x93933DAEL, 0x26264C6AL,
  0x36366C5AL, 0x3F3F7E41L, 0xF7F7F502L, 0xCCCC834FL,
  0x3434685CL, 0xA5A551F4L, 0xE5E5D134L, 0xF1F1F908L,
  0x7171E293L, 0xD8D8AB73L, 0x31316253L, 0x15152A3FL,
  0x0404080CL, 0xC7C79552L, 0x23234665L, 0xC3C39D5EL,
  0x18183028L, 0x969637A1L, 0x05050A0FL, 0x9A9A2FB5L,
  0x07070E09L, 0x12122436L, 0x80801B9BL, 0xE2E2DF3DL,
  0xEBEBCD26L, 0x27274E69L, 0xB2B27FCDL, 0x7575EA9FL,
  0x0909121BL, 0x83831D9EL, 0x2C2C5874L, 0x1A1A342EL,
  0x1B1B362DL, 0x6E6EDCB2L, 0x5A5AB4EEL, 0xA0A05BFBL,
  0x5252A4F6L, 0x3B3B764DL, 0xD6D6B761L, 0xB3B37DCEL,
  0x2929527BL, 0xE3E3DD3EL, 0x2F2F5E71L, 0x84841397L,
  0x5353A6F5L, 0xD1D1B968L, 0x00000000L, 0xEDEDC12CL,
  0x20204060L, 0xFCFCE31FL, 0xB1B179C8L, 0x5B5BB6EDL,
  0x6A6AD4BEL, 0xCBCB8D46L, 0xBEBE67D9L, 0x3939724BL,
  0x4A4A94DEL, 0x4C4C98D4L, 0x5858B0E8L, 0xCFCF854AL,
  0xD0D0BB6BL, 0xEFEFC52AL, 0xAAAA4FE5L, 0xFBFBED16L,
  0x434386C5L, 0x4D4D9AD7L, 0x33336655L, 0x85851194L,
  0x45458ACFL, 0xF9F9E910L, 0x02020406L, 0x7F7FFE81L,
  0x5050A0F0L, 0x3C3C7844L, 0x9F9F25BAL, 0xA8A84BE3L,
  0x5151A2F3L, 0xA3A35DFEL, 0x404080C0L, 0x8F8F058AL,
  0x92923FADL, 0x9D9D21BCL, 0x38387048L, 0xF5F5F104L,
  0xBCBC63DFL, 0xB6B677C1L, 0xDADAAF75L, 0x21214263L,
  0x10102030L, 0xFFFFE51AL, 0xF3F3FD0EL, 0xD2D2BF6DL,
  0xCDCD814CL, 0x0C0C1814L, 0x13132635L, 0xECECC32FL,
  0x5F5FBEE1L, 0x979735A2L, 0x444488CCL, 0x17172E39L,
  0xC4C49357L, 0xA7A755F2L, 0x7E7EFC82L, 0x3D3D7A47L,
  0x6464C8ACL, 0x5D5DBAE7L, 0x1919322BL, 0x7373E695L,
  0x6060C0A0L, 0x81811998L, 0x4F4F9ED1L, 0xDCDCA37FL,
  0x22224466L, 0x2A2A547EL, 0x90903BABL, 0x88880B83L,
  0x46468CCAL, 0xEEEEC729L, 0xB8B86BD3L, 0x1414283CL,
  0xDEDEA779L, 0x5E5EBCE2L, 0x0B0B161DL, 0xDBDBAD76L,
  0xE0E0DB3BL, 0x32326456L, 0x3A3A744EL, 0x0A0A141EL,
  0x494992DBL, 0x06060C0AL, 0x2424486CL, 0x5C5CB8E4L,
  0xC2C29F5DL, 0xD3D3BD6EL, 0xACAC43EFL, 0x6262C4A6L,
  0x919139A8L, 0x959531A4L, 0xE4E4D337L, 0x7979F28BL,
  0xE7E7D532L, 0xC8C88B43L, 0x37376E59L, 0x6D6DDAB7L,
  0x8D8D018CL, 0xD5D5B164L, 0x4E4E9CD2L, 0xA9A949E0L,
  0x6C6CD8B4L, 0x5656ACFAL, 0xF4F4F307L, 0xEAEACF25L,
  0x6565CAAFL, 0x7A7AF48EL, 0xAEAE47E9L, 0x08081018L,
  0xBABA6FD5L, 0x7878F088L, 0x25254A6FL, 0x2E2E5C72L,
  0x1C1C3824L, 0xA6A657F1L, 0xB4B473C7L, 0xC6C69751L,
  0xE8E8CB23L, 0xDDDDA17CL, 0x7474E89CL, 0x1F1F3E21L,
  0x4B4B96DDL, 0xBDBD61DCL, 0x8B8B0D86L, 0x8A8A0F85L,
  0x7070E090L, 0x3E3E7C42L, 0xB5B571C4L, 0x6666CCAAL,
  0x484890D8L, 0x03030605L, 0xF6F6F701L, 0x0E0E1C12L,
  0x6161C2A3L, 0x35356A5FL, 0x5757AEF9L, 0xB9B969D0L,
  0x86861791L, 0xC1C19958L, 0x1D1D3A27L, 0x9E9E27B9L,
  0xE1E1D938L, 0xF8F8EB13L, 0x98982BB3L, 0x11112233L,
  0x6969D2BBL, 0xD9D9A970L, 0x8E8E0789L, 0x949433A7L,
  0x9B9B2DB6L, 0x1E1E3C22L, 0x87871592L, 0xE9E9C920L,
  0xCECE8749L, 0x5555AAFFL, 0x28285078L, 0xDFDFA57AL,
  0x8C8C038FL, 0xA1A159F8L, 0x89890980L, 0x0D0D1A17L,
  0xBFBF65DAL, 0xE6E6D731L, 0x424284C6L, 0x6868D0B8L,
  0x414182C3L, 0x999929B0L, 0x2D2D5A77L, 0x0F0F1E11L,
  0xB0B07BCBL, 0x5454A8FCL, 0xBBBB6DD6L, 0x16162C3AL
};

static const unsigned long crypto_aes_sbox3[256] =
{
  0x63C6A563L, 0x7CF8847CL, 0x77EE9977L, 0x7BF68D7BL,
  0xF2FF0DF2L, 0x6BD6BD6BL, 0x6FDEB16FL, 0xC59154C5L,
  0x30605030L, 0x01020301L, 0x67CEA967L, 0x2B567D2BL,
  0xFEE719FEL, 0xD7B562D7L, 0xAB4DE6ABL, 0x76EC9A76L,
  0xCA8F45CAL, 0x821F9D82L, 0xC98940C9L, 0x7DFA877DL,
  0xFAEF15FAL, 0x59B2EB59L, 0x478EC947L, 0xF0FB0BF0L,
  0xAD41ECADL, 0xD4B367D4L, 0xA25FFDA2L, 0xAF45EAAFL,
  0x9C23BF9CL, 0xA453F7A4L, 0x72E49672L, 0xC09B5BC0L,
  0xB775C2B7L, 0xFDE11CFDL, 0x933DAE93L, 0x264C6A26L,
  0x366C5A36L, 0x3F7E413FL, 0xF7F502F7L, 0xCC834FCCL,
  0x34685C34L, 0xA551F4A5L, 0xE5D134E5L, 0xF1F908F1L,
  0x71E29371L, 0xD8AB73D8L, 0x31625331L, 0x152A3F15L,
  0x04080C04L, 0xC79552C7L, 0x23466523L, 0xC39D5EC3L,
  0x18302818L, 0x9637A196L, 0x050A0F05L, 0x9A2FB59AL,
  0x070E0907L, 0x12243612L, 0x801B9B80L, 0xE2DF3DE2L,
  0xEBCD26EBL, 0x274E6927L, 0xB27FCDB2L, 0x75EA9F75L,
  0x09121B09L, 0x831D9E83L, 0x2C58742CL, 0x1A342E1AL,
  0x1B362D1BL, 0x6EDCB26EL, 0x5AB4EE5AL, 0xA05BFBA0L,
  0x52A4F652L, 0x3B764D3BL, 0xD6B761D6L, 0xB37DCEB3L,
  0x29527B29L, 0xE3DD3EE3L, 0x2F5E712FL, 0x84139784L,
  0x53A6F553L, 0xD1B968D1L, 0x00000000L, 0xEDC12CEDL,
  0x20406020L, 0xFCE31FFCL, 0xB179C8B1L, 0x5BB6ED5BL,
  0x6AD4BE6AL, 0xCB8D46CBL, 0xBE67D9BEL, 0x39724B39L,
  0x4A94DE4AL, 0x4C98D44CL, 0x58B0E858L, 0xCF854ACFL,
  0xD0BB6BD0L, 0xEFC52AEFL, 0xAA4FE5AAL, 0xFBED16FBL,
  0x4386C543L, 0x4D9AD74DL, 0x33665533L, 0x85119485L,
  0x458ACF45L, 0xF9E910F9L, 0x02040602L, 0x7FFE817FL,
  0x50A0F050L, 0x3C78443CL, 0x9F25BA9FL, 0xA84BE3A8L,
  0x51A2F351L, 0xA35DFEA3L, 0x4080C040L, 0x8F058A8FL,
  0x923FAD92L, 0x9D21BC9DL, 0x38704838L, 0xF5F104F5L,
  0xBC63DFBCL, 0xB677C1B6L, 0xDAAF75DAL, 0x21426321L,
  0x10203010L, 0xFFE51AFFL, 0xF3FD0EF3L, 0xD2BF6DD2L,
  0xCD814CCDL, 0x0C18140CL, 0x13263513L, 0xECC32FECL,
  0x5FBEE15FL, 0x9735A297L, 0x4488CC44L, 0x172E3917L,
  0xC49357C4L, 0xA755F2A7L, 0x7EFC827EL, 0x3D7A473DL,
  0x64C8AC64L, 0x5DBAE75DL, 0x19322B19L, 0x73E69573L,
  0x60C0A060L, 0x81199881L, 0x4F9ED14FL, 0xDCA37FDCL,
  0x22446622L, 0x2A547E2AL, 0x903BAB90L, 0x880B8388L,
  0x468CCA46L, 0xEEC729EEL, 0xB86BD3B8L, 0x14283C14L,
  0xDEA779DEL, 0x5EBCE25EL, 0x0B161D0BL, 0xDBAD76DBL,
  0xE0DB3BE0L, 0x32645632L, 0x3A744E3AL, 0x0A141E0AL,
  0x4992DB49L, 0x060C0A06L, 0x24486C24L, 0x5CB8E45CL,
  0xC29F5DC2L, 0xD3BD6ED3L, 0xAC43EFACL, 0x62C4A662L,
  0x9139A891L, 0x9531A495L, 0xE4D337E4L, 0x79F28B79L,
  0xE7D532E7L, 0xC88B43C8L, 0x376E5937L, 0x6DDAB76DL,
  0x8D018C8DL, 0xD5B164D5L, 0x4E9CD24EL, 0xA949E0A9L,
  0x6CD8B46CL, 0x56ACFA56L, 0xF4F307F4L, 0xEACF25EAL,
  0x65CAAF65L, 0x7AF48E7AL, 0xAE47E9AEL, 0x08101808L,
  0xBA6FD5BAL, 0x78F08878L, 0x254A6F25L, 0x2E5C722EL,
  0x1C38241CL, 0xA657F1A6L, 0xB473C7B4L, 0xC69751C6L,
  0xE8CB23E8L, 0xDDA17CDDL, 0x74E89C74L, 0x1F3E211FL,
  0x4B96DD4BL, 0xBD61DCBDL, 0x8B0D868BL, 0x8A0F858AL,
  0x70E09070L, 0x3E7C423EL, 0xB571C4B5L, 0x66CCAA66L,
  0x4890D848L, 0x03060503L, 0xF6F701F6L, 0x0E1C120EL,
  0x61C2A361L, 0x356A5F35L, 0x57AEF957L, 0xB969D0B9L,
  0x86179186L, 0xC19958C1L, 0x1D3A271DL, 0x9E27B99EL,
  0xE1D938E1L, 0xF8EB13F8L, 0x982BB398L, 0x11223311L,
  0x69D2BB69L, 0xD9A970D9L, 0x8E07898EL, 0x9433A794L,
  0x9B2DB69BL, 0x1E3C221EL, 0x87159287L, 0xE9C920E9L,
  0xCE8749CEL, 0x55AAFF55L, 0x28507828L, 0xDFA57ADFL,
  0x8C038F8CL, 0xA159F8A1L, 0x89098089L, 0x0D1A170DL,
  0xBF65DABFL, 0xE6D731E6L, 0x4284C642L, 0x68D0B868L,
  0x4182C341L, 0x9929B099L, 0x2D5A772DL, 0x0F1E110FL,
  0xB07BCBB0L, 0x54A8FC54L, 0xBB6DD6BBL, 0x162C3A16L
};

static const unsigned long crypto_aes_sbox4[256] =
{
  0xC6A56363L, 0xF8847C7CL, 0xEE997777L, 0xF68D7B7BL,
  0xFF0DF2F2L, 0xD6BD6B6BL, 0xDEB16F6FL, 0x9154C5C5L,
  0x60503030L, 0x02030101L, 0xCEA96767L, 0x567D2B2BL,
  0xE719FEFEL, 0xB562D7D7L, 0x4DE6ABABL, 0xEC9A7676L,
  0x8F45CACAL, 0x1F9D8282L, 0x8940C9C9L, 0xFA877D7DL,
  0xEF15FAFAL, 0xB2EB5959L, 0x8EC94747L, 0xFB0BF0F0L,
  0x41ECADADL, 0xB367D4D4L, 0x5FFDA2A2L, 0x45EAAFAFL,
  0x23BF9C9CL, 0x53F7A4A4L, 0xE4967272L, 0x9B5BC0C0L,
  0x75C2B7B7L, 0xE11CFDFDL, 0x3DAE9393L, 0x4C6A2626L,
  0x6C5A3636L, 0x7E413F3FL, 0xF502F7F7L, 0x834FCCCCL,
  0x685C3434L, 0x51F4A5A5L, 0xD134E5E5L, 0xF908F1F1L,
  0xE2937171L, 0xAB73D8D8L, 0x62533131L, 0x2A3F1515L,
  0x080C0404L, 0x9552C7C7L, 0x46652323L, 0x9D5EC3C3L,
  0x30281818L, 0x37A19696L, 0x0A0F0505L, 0x2FB59A9AL,
  0x0E090707L, 0x24361212L, 0x1B9B8080L, 0xDF3DE2E2L,
  0xCD26EBEBL, 0x4E692727L, 0x7FCDB2B2L, 0xEA9F7575L,
  0x121B0909L, 0x1D9E8383L, 0x58742C2CL, 0x342E1A1AL,
  0x362D1B1BL, 0xDCB26E6EL, 0xB4EE5A5AL, 0x5BFBA0A0L,
  0xA4F65252L, 0x764D3B3BL, 0xB761D6D6L, 0x7DCEB3B3L,
  0x527B2929L, 0xDD3EE3E3L, 0x5E712F2FL, 0x13978484L,
  0xA6F55353L, 0xB968D1D1L, 0x00000000L, 0xC12CEDEDL,
  0x40602020L, 0xE31FFCFCL, 0x79C8B1B1L, 0xB6ED5B5BL,
  0xD4BE6A6AL, 0x8D46CBCBL, 0x67D9BEBEL, 0x724B3939L,
  0x94DE4A4AL, 0x98D44C4CL, 0xB0E85858L, 0x854ACFCFL,
  0xBB6BD0D0L, 0xC52AEFEFL, 0x4FE5AAAAL, 0xED16FBFBL,
  0x86C54343L, 0x9AD74D4DL, 0x66553333L, 0x11948585L,
  0x8ACF4545L, 0xE910F9F9L, 0x04060202L, 0xFE817F7FL,
  0xA0F05050L, 0x78443C3CL, 0x25BA9F9FL, 0x4BE3A8A8L,
  0xA2F35151L, 0x5DFEA3A3L, 0x80C04040L, 0x058A8F8FL,
  0x3FAD9292L, 0x21BC9D9DL, 0x70483838L, 0xF104F5F5L,
  0x63DFBCBCL, 0x77C1B6B6L, 0xAF75DADAL, 0x42632121L,
  0x20301010L, 0xE51AFFFFL, 0xFD0EF3F3L, 0xBF6DD2D2L,
  0x814CCDCDL, 0x18140C0CL, 0x26351313L, 0xC32FECECL,
  0xBEE15F5FL, 0x35A29797L, 0x88CC4444L, 0x2E391717L,
  0x9357C4C4L, 0x55F2A7A7L, 0xFC827E7EL, 0x7A473D3DL,
  0xC8AC6464L, 0xBAE75D5DL, 0x322B1919L, 0xE6957373L,
  0xC0A06060L, 0x19988181L, 0x9ED14F4FL, 0xA37FDCDCL,
  0x44662222L, 0x547E2A2AL, 0x3BAB9090L, 0x0B838888L,
  0x8CCA4646L, 0xC729EEEEL, 0x6BD3B8B8L, 0x283C1414L,
  0xA779DEDEL, 0xBCE25E5EL, 0x161D0B0BL, 0xAD76DBDBL,
  0xDB3BE0E0L, 0x64563232L, 0x744E3A3AL, 0x141E0A0AL,
  0x92DB4949L, 0x0C0A0606L, 0x486C2424L, 0xB8E45C5CL,
  0x9F5DC2C2L, 0xBD6ED3D3L, 0x43EFACACL, 0xC4A66262L,
  0x39A89191L, 0x31A49595L, 0xD337E4E4L, 0xF28B7979L,
  0xD532E7E7L, 0x8B43C8C8L, 0x6E593737L, 0xDAB76D6DL,
  0x018C8D8DL, 0xB164D5D5L, 0x9CD24E4EL, 0x49E0A9A9L,
  0xD8B46C6CL, 0xACFA5656L, 0xF307F4F4L, 0xCF25EAEAL,
  0xCAAF6565L, 0xF48E7A7AL, 0x47E9AEAEL, 0x10180808L,
  0x6FD5BABAL, 0xF0887878L, 0x4A6F2525L, 0x5C722E2EL,
  0x38241C1CL, 0x57F1A6A6L, 0x73C7B4B4L, 0x9751C6C6L,
  0xCB23E8E8L, 0xA17CDDDDL, 0xE89C7474L, 0x3E211F1FL,
  0x96DD4B4BL, 0x61DCBDBDL, 0x0D868B8BL, 0x0F858A8AL,
  0xE0907070L, 0x7C423E3EL, 0x71C4B5B5L, 0xCCAA6666L,
  0x90D84848L, 0x06050303L, 0xF701F6F6L, 0x1C120E0EL,
  0xC2A36161L, 0x6A5F3535L, 0xAEF95757L, 0x69D0B9B9L,
  0x17918686L, 0x9958C1C1L, 0x3A271D1DL, 0x27B99E9EL,
  0xD938E1E1L, 0xEB13F8F8L, 0x2BB39898L, 0x22331111L,
  0xD2BB6969L, 0xA970D9D9L, 0x07898E8EL, 0x33A79494L,
  0x2DB69B9BL, 0x3C221E1EL, 0x15928787L, 0xC920E9E9L,
  0x8749CECEL, 0xAAFF5555L, 0x50782828L, 0xA57ADFDFL,
  0x038F8C8CL, 0x59F8A1A1L, 0x09808989L, 0x1A170D0DL,
  0x65DABFBFL, 0xD731E6E6L, 0x84C64242L, 0xD0B86868L,
  0x82C34141L, 0x29B09999L, 0x5A772D2DL, 0x1E110F0FL,
  0x7BCBB0B0L, 0xA8FC5454L, 0x6DD6BBBBL, 0x2C3A1616L
};

/*----*/

static const unsigned char crypto_twofish_sbox0[256]=
{
  0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
  0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
  0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
  0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
  0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
  0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
  0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
  0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
  0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
  0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
  0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
  0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
  0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
  0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
  0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
  0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
  0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
  0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
  0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
  0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
  0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
  0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
  0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
  0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
  0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
  0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
  0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
  0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
  0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
  0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
  0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
  0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
};

static const unsigned char crypto_twofish_sbox1[256]=
{
  0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
  0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
  0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
  0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
  0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
  0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
  0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
  0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
  0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
  0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
  0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
  0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
  0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
  0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
  0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
  0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
  0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
  0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
  0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
  0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
  0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
  0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
  0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
  0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
  0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
  0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
  0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
  0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
  0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
  0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
  0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
  0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
};

/*--*/

static const unsigned long crypto_twofish_mds0[256] =
{
  0xBCBC3275L, 0xECEC21F3L, 0x202043C6L, 0xB3B3C9F4L,
  0xDADA03DBL, 0x02028B7BL, 0xE2E22BFBL, 0x9E9EFAC8L,
  0xC9C9EC4AL, 0xD4D409D3L, 0x18186BE6L, 0x1E1E9F6BL,
  0x98980E45L, 0xB2B2387DL, 0xA6A6D2E8L, 0x2626B74BL,
  0x3C3C57D6L, 0x93938A32L, 0x8282EED8L, 0x525298FDL,
  0x7B7BD437L, 0xBBBB3771L, 0x5B5B97F1L, 0x474783E1L,
  0x24243C30L, 0x5151E20FL, 0xBABAC6F8L, 0x4A4AF31BL,
  0xBFBF4887L, 0x0D0D70FAL, 0xB0B0B306L, 0x7575DE3FL,
  0xD2D2FD5EL, 0x7D7D20BAL, 0x666631AEL, 0x3A3AA35BL,
  0x59591C8AL, 0x00000000L, 0xCDCD93BCL, 0x1A1AE09DL,
  0xAEAE2C6DL, 0x7F7FABC1L, 0x2B2BC7B1L, 0xBEBEB90EL,
  0xE0E0A080L, 0x8A8A105DL, 0x3B3B52D2L, 0x6464BAD5L,
  0xD8D888A0L, 0xE7E7A584L, 0x5F5FE807L, 0x1B1B1114L,
  0x2C2CC2B5L, 0xFCFCB490L, 0x3131272CL, 0x808065A3L,
  0x73732AB2L, 0x0C0C8173L, 0x79795F4CL, 0x6B6B4154L,
  0x4B4B0292L, 0x53536974L, 0x94948F36L, 0x83831F51L,
  0x2A2A3638L, 0xC4C49CB0L, 0x2222C8BDL, 0xD5D5F85AL,
  0xBDBDC3FCL, 0x48487860L, 0xFFFFCE62L, 0x4C4C0796L,
  0x4141776CL, 0xC7C7E642L, 0xEBEB24F7L, 0x1C1C1410L,
  0x5D5D637CL, 0x36362228L, 0x6767C027L, 0xE9E9AF8CL,
  0x4444F913L, 0x1414EA95L, 0xF5F5BB9CL, 0xCFCF18C7L,
  0x3F3F2D24L, 0xC0C0E346L, 0x7272DB3BL, 0x54546C70L,
  0x29294CCAL, 0xF0F035E3L, 0x0808FE85L, 0xC6C617CBL,
  0xF3F34F11L, 0x8C8CE4D0L, 0xA4A45993L, 0xCACA96B8L,
  0x68683BA6L, 0xB8B84D83L, 0x38382820L, 0xE5E52EFFL,
  0xADAD569FL, 0x0B0B8477L, 0xC8C81DC3L, 0x9999FFCCL,
  0x5858ED03L, 0x19199A6FL, 0x0E0E0A08L, 0x95957EBFL,
  0x70705040L, 0xF7F730E7L, 0x6E6ECF2BL, 0x1F1F6EE2L,
  0xB5B53D79L, 0x09090F0CL, 0x616134AAL, 0x57571682L,
  0x9F9F0B41L, 0x9D9D803AL, 0x111164EAL, 0x2525CDB9L,
  0xAFAFDDE4L, 0x4545089AL, 0xDFDF8DA4L, 0xA3A35C97L,
  0xEAEAD57EL, 0x353558DAL, 0xEDEDD07AL, 0x4343FC17L,
  0xF8F8CB66L, 0xFBFBB194L, 0x3737D3A1L, 0xFAFA401DL,
  0xC2C2683DL, 0xB4B4CCF0L, 0x32325DDEL, 0x9C9C71B3L,
  0x5656E70BL, 0xE3E3DA72L, 0x878760A7L, 0x15151B1CL,
  0xF9F93AEFL, 0x6363BFD1L, 0x3434A953L, 0x9A9A853EL,
  0xB1B1428FL, 0x7C7CD133L, 0x88889B26L, 0x3D3DA65FL,
  0xA1A1D7ECL, 0xE4E4DF76L, 0x8181942AL, 0x91910149L,
  0x0F0FFB81L, 0xEEEEAA88L, 0x161661EEL, 0xD7D77321L,
  0x9797F5C4L, 0xA5A5A81AL, 0xFEFE3FEBL, 0x6D6DB5D9L,
  0x7878AEC5L, 0xC5C56D39L, 0x1D1DE599L, 0x7676A4CDL,
  0x3E3EDCADL, 0xCBCB6731L, 0xB6B6478BL, 0xEFEF5B01L,
  0x12121E18L, 0x6060C523L, 0x6A6AB0DDL, 0x4D4DF61FL,
  0xCECEE94EL, 0xDEDE7C2DL, 0x55559DF9L, 0x7E7E5A48L,
  0x2121B24FL, 0x03037AF2L, 0xA0A02665L, 0x5E5E198EL,
  0x5A5A6678L, 0x65654B5CL, 0x62624E58L, 0xFDFD4519L,
  0x0606F48DL, 0x404086E5L, 0xF2F2BE98L, 0x3333AC57L,
  0x17179067L, 0x05058E7FL, 0xE8E85E05L, 0x4F4F7D64L,
  0x89896AAFL, 0x10109563L, 0x74742FB6L, 0x0A0A75FEL,
  0x5C5C92F5L, 0x9B9B74B7L, 0x2D2D333CL, 0x3030D6A5L,
  0x2E2E49CEL, 0x494989E9L, 0x46467268L, 0x77775544L,
  0xA8A8D8E0L, 0x9696044DL, 0x2828BD43L, 0xA9A92969L,
  0xD9D97929L, 0x8686912EL, 0xD1D187ACL, 0xF4F44A15L,
  0x8D8D1559L, 0xD6D682A8L, 0xB9B9BC0AL, 0x42420D9EL,
  0xF6F6C16EL, 0x2F2FB847L, 0xDDDD06DFL, 0x23233934L,
  0xCCCC6235L, 0xF1F1C46AL, 0xC1C112CFL, 0x8585EBDCL,
  0x8F8F9E22L, 0x7171A1C9L, 0x9090F0C0L, 0xAAAA539BL,
  0x0101F189L, 0x8B8BE1D4L, 0x4E4E8CEDL, 0x8E8E6FABL,
  0xABABA212L, 0x6F6F3EA2L, 0xE6E6540DL, 0xDBDBF252L,
  0x92927BBBL, 0xB7B7B602L, 0x6969CA2FL, 0x3939D9A9L,
  0xD3D30CD7L, 0xA7A72361L, 0xA2A2AD1EL, 0xC3C399B4L,
  0x6C6C4450L, 0x07070504L, 0x04047FF6L, 0x272746C2L,
  0xACACA716L, 0xD0D07625L, 0x50501386L, 0xDCDCF756L,
  0x84841A55L, 0xE1E15109L, 0x7A7A25BEL, 0x1313EF91L
};

static const unsigned long crypto_twofish_mds1[256] =
{
  0xA9D93939L, 0x67901717L, 0xB3719C9CL, 0xE8D2A6A6L,
  0x04050707L, 0xFD985252L, 0xA3658080L, 0x76DFE4E4L,
  0x9A084545L, 0x92024B4BL, 0x80A0E0E0L, 0x78665A5AL,
  0xE4DDAFAFL, 0xDDB06A6AL, 0xD1BF6363L, 0x38362A2AL,
  0x0D54E6E6L, 0xC6432020L, 0x3562CCCCL, 0x98BEF2F2L,
  0x181E1212L, 0xF724EBEBL, 0xECD7A1A1L, 0x6C774141L,
  0x43BD2828L, 0x7532BCBCL, 0x37D47B7BL, 0x269B8888L,
  0xFA700D0DL, 0x13F94444L, 0x94B1FBFBL, 0x485A7E7EL,
  0xF27A0303L, 0xD0E48C8CL, 0x8B47B6B6L, 0x303C2424L,
  0x84A5E7E7L, 0x54416B6BL, 0xDF06DDDDL, 0x23C56060L,
  0x1945FDFDL, 0x5BA33A3AL, 0x3D68C2C2L, 0x59158D8DL,
  0xF321ECECL, 0xAE316666L, 0xA23E6F6FL, 0x82165757L,
  0x63951010L, 0x015BEFEFL, 0x834DB8B8L, 0x2E918686L,
  0xD9B56D6DL, 0x511F8383L, 0x9B53AAAAL, 0x7C635D5DL,
  0xA63B6868L, 0xEB3FFEFEL, 0xA5D63030L, 0xBE257A7AL,
  0x16A7ACACL, 0x0C0F0909L, 0xE335F0F0L, 0x6123A7A7L,
  0xC0F09090L, 0x8CAFE9E9L, 0x3A809D9DL, 0xF5925C5CL,
  0x73810C0CL, 0x2C273131L, 0x2576D0D0L, 0x0BE75656L,
  0xBB7B9292L, 0x4EE9CECEL, 0x89F10101L, 0x6B9F1E1EL,
  0x53A93434L, 0x6AC4F1F1L, 0xB499C3C3L, 0xF1975B5BL,
  0xE1834747L, 0xE66B1818L, 0xBDC82222L, 0x450E9898L,
  0xE26E1F1FL, 0xF4C9B3B3L, 0xB62F7474L, 0x66CBF8F8L,
  0xCCFF9999L, 0x95EA1414L, 0x03ED5858L, 0x56F7DCDCL,
  0xD4E18B8BL, 0x1C1B1515L, 0x1EADA2A2L, 0xD70CD3D3L,
  0xFB2BE2E2L, 0xC31DC8C8L, 0x8E195E5EL, 0xB5C22C2CL,
  0xE9894949L, 0xCF12C1C1L, 0xBF7E9595L, 0xBA207D7DL,
  0xEA641111L, 0x77840B0BL, 0x396DC5C5L, 0xAF6A8989L,
  0x33D17C7CL, 0xC9A17171L, 0x62CEFFFFL, 0x7137BBBBL,
  0x81FB0F0FL, 0x793DB5B5L, 0x0951E1E1L, 0xADDC3E3EL,
  0x242D3F3FL, 0xCDA47676L, 0xF99D5555L, 0xD8EE8282L,
  0xE5864040L, 0xC5AE7878L, 0xB9CD2525L, 0x4D049696L,
  0x44557777L, 0x080A0E0EL, 0x86135050L, 0xE730F7F7L,
  0xA1D33737L, 0x1D40FAFAL, 0xAA346161L, 0xED8C4E4EL,
  0x06B3B0B0L, 0x706C5454L, 0xB22A7373L, 0xD2523B3BL,
  0x410B9F9FL, 0x7B8B0202L, 0xA088D8D8L, 0x114FF3F3L,
  0x3167CBCBL, 0xC2462727L, 0x27C06767L, 0x90B4FCFCL,
  0x20283838L, 0xF67F0404L, 0x60784848L, 0xFF2EE5E5L,
  0x96074C4CL, 0x5C4B6565L, 0xB1C72B2BL, 0xAB6F8E8EL,
  0x9E0D4242L, 0x9CBBF5F5L, 0x52F2DBDBL, 0x1BF34A4AL,
  0x5FA63D3DL, 0x9359A4A4L, 0x0ABCB9B9L, 0xEF3AF9F9L,
  0x91EF1313L, 0x85FE0808L, 0x49019191L, 0xEE611616L,
  0x2D7CDEDEL, 0x4FB22121L, 0x8F42B1B1L, 0x3BDB7272L,
  0x47B82F2FL, 0x8748BFBFL, 0x6D2CAEAEL, 0x46E3C0C0L,
  0xD6573C3CL, 0x3E859A9AL, 0x6929A9A9L, 0x647D4F4FL,
  0x2A948181L, 0xCE492E2EL, 0xCB17C6C6L, 0x2FCA6969L,
  0xFCC3BDBDL, 0x975CA3A3L, 0x055EE8E8L, 0x7AD0EDEDL,
  0xAC87D1D1L, 0x7F8E0505L, 0xD5BA6464L, 0x1AA8A5A5L,
  0x4BB72626L, 0x0EB9BEBEL, 0xA7608787L, 0x5AF8D5D5L,
  0x28223636L, 0x14111B1BL, 0x3FDE7575L, 0x2979D9D9L,
  0x88AAEEEEL, 0x3C332D2DL, 0x4C5F7979L, 0x02B6B7B7L,
  0xB896CACAL, 0xDA583535L, 0xB09CC4C4L, 0x17FC4343L,
  0x551A8484L, 0x1FF64D4DL, 0x8A1C5959L, 0x7D38B2B2L,
  0x57AC3333L, 0xC718CFCFL, 0x8DF40606L, 0x74695353L,
  0xB7749B9BL, 0xC4F59797L, 0x9F56ADADL, 0x72DAE3E3L,
  0x7ED5EAEAL, 0x154AF4F4L, 0x229E8F8FL, 0x12A2ABABL,
  0x584E6262L, 0x07E85F5FL, 0x99E51D1DL, 0x34392323L,
  0x6EC1F6F6L, 0x50446C6CL, 0xDE5D3232L, 0x68724646L,
  0x6526A0A0L, 0xBC93CDCDL, 0xDB03DADAL, 0xF8C6BABAL,
  0xC8FA9E9EL, 0xA882D6D6L, 0x2BCF6E6EL, 0x40507070L,
  0xDCEB8585L, 0xFE750A0AL, 0x328A9393L, 0xA48DDFDFL,
  0xCA4C2929L, 0x10141C1CL, 0x2173D7D7L, 0xF0CCB4B4L,
  0xD309D4D4L, 0x5D108A8AL, 0x0FE25151L, 0x00000000L,
  0x6F9A1919L, 0x9DE01A1AL, 0x368F9494L, 0x42E6C7C7L,
  0x4AECC9C9L, 0x5EFDD2D2L, 0xC1AB7F7FL, 0xE0D8A8A8L
};

static const unsigned long crypto_twofish_mds2[256] =
{
  0xBC75BC32L, 0xECF3EC21L, 0x20C62043L, 0xB3F4B3C9L,
  0xDADBDA03L, 0x027B028BL, 0xE2FBE22BL, 0x9EC89EFAL,
  0xC94AC9ECL, 0xD4D3D409L, 0x18E6186BL, 0x1E6B1E9FL,
  0x9845980EL, 0xB27DB238L, 0xA6E8A6D2L, 0x264B26B7L,
  0x3CD63C57L, 0x9332938AL, 0x82D882EEL, 0x52FD5298L,
  0x7B377BD4L, 0xBB71BB37L, 0x5BF15B97L, 0x47E14783L,
  0x2430243CL, 0x510F51E2L, 0xBAF8BAC6L, 0x4A1B4AF3L,
  0xBF87BF48L, 0x0DFA0D70L, 0xB006B0B3L, 0x753F75DEL,
  0xD25ED2FDL, 0x7DBA7D20L, 0x66AE6631L, 0x3A5B3AA3L,
  0x598A591CL, 0x00000000L, 0xCDBCCD93L, 0x1A9D1AE0L,
  0xAE6DAE2CL, 0x7FC17FABL, 0x2BB12BC7L, 0xBE0EBEB9L,
  0xE080E0A0L, 0x8A5D8A10L, 0x3BD23B52L, 0x64D564BAL,
  0xD8A0D888L, 0xE784E7A5L, 0x5F075FE8L, 0x1B141B11L,
  0x2CB52CC2L, 0xFC90FCB4L, 0x312C3127L, 0x80A38065L,
  0x73B2732AL, 0x0C730C81L, 0x794C795FL, 0x6B546B41L,
  0x4B924B02L, 0x53745369L, 0x9436948FL, 0x8351831FL,
  0x2A382A36L, 0xC4B0C49CL, 0x22BD22C8L, 0xD55AD5F8L,
  0xBDFCBDC3L, 0x48604878L, 0xFF62FFCEL, 0x4C964C07L,
  0x416C4177L, 0xC742C7E6L, 0xEBF7EB24L, 0x1C101C14L,
  0x5D7C5D63L, 0x36283622L, 0x672767C0L, 0xE98CE9AFL,
  0x441344F9L, 0x149514EAL, 0xF59CF5BBL, 0xCFC7CF18L,
  0x3F243F2DL, 0xC046C0E3L, 0x723B72DBL, 0x5470546CL,
  0x29CA294CL, 0xF0E3F035L, 0x088508FEL, 0xC6CBC617L,
  0xF311F34FL, 0x8CD08CE4L, 0xA493A459L, 0xCAB8CA96L,
  0x68A6683BL, 0xB883B84DL, 0x38203828L, 0xE5FFE52EL,
  0xAD9FAD56L, 0x0B770B84L, 0xC8C3C81DL, 0x99CC99FFL,
  0x580358EDL, 0x196F199AL, 0x0E080E0AL, 0x95BF957EL,
  0x70407050L, 0xF7E7F730L, 0x6E2B6ECFL, 0x1FE21F6EL,
  0xB579B53DL, 0x090C090FL, 0x61AA6134L, 0x57825716L,
  0x9F419F0BL, 0x9D3A9D80L, 0x11EA1164L, 0x25B925CDL,
  0xAFE4AFDDL, 0x459A4508L, 0xDFA4DF8DL, 0xA397A35CL,
  0xEA7EEAD5L, 0x35DA3558L, 0xED7AEDD0L, 0x431743FCL,
  0xF866F8CBL, 0xFB94FBB1L, 0x37A137D3L, 0xFA1DFA40L,
  0xC23DC268L, 0xB4F0B4CCL, 0x32DE325DL, 0x9CB39C71L,
  0x560B56E7L, 0xE372E3DAL, 0x87A78760L, 0x151C151BL,
  0xF9EFF93AL, 0x63D163BFL, 0x345334A9L, 0x9A3E9A85L,
  0xB18FB142L, 0x7C337CD1L, 0x8826889BL, 0x3D5F3DA6L,
  0xA1ECA1D7L, 0xE476E4DFL, 0x812A8194L, 0x91499101L,
  0x0F810FFBL, 0xEE88EEAAL, 0x16EE1661L, 0xD721D773L,
  0x97C497F5L, 0xA51AA5A8L, 0xFEEBFE3FL, 0x6DD96DB5L,
  0x78C578AEL, 0xC539C56DL, 0x1D991DE5L, 0x76CD76A4L,
  0x3EAD3EDCL, 0xCB31CB67L, 0xB68BB647L, 0xEF01EF5BL,
  0x1218121EL, 0x602360C5L, 0x6ADD6AB0L, 0x4D1F4DF6L,
  0xCE4ECEE9L, 0xDE2DDE7CL, 0x55F9559DL, 0x7E487E5AL,
  0x214F21B2L, 0x03F2037AL, 0xA065A026L, 0x5E8E5E19L,
  0x5A785A66L, 0x655C654BL, 0x6258624EL, 0xFD19FD45L,
  0x068D06F4L, 0x40E54086L, 0xF298F2BEL, 0x335733ACL,
  0x17671790L, 0x057F058EL, 0xE805E85EL, 0x4F644F7DL,
  0x89AF896AL, 0x10631095L, 0x74B6742FL, 0x0AFE0A75L,
  0x5CF55C92L, 0x9BB79B74L, 0x2D3C2D33L, 0x30A530D6L,
  0x2ECE2E49L, 0x49E94989L, 0x46684672L, 0x77447755L,
  0xA8E0A8D8L, 0x964D9604L, 0x284328BDL, 0xA969A929L,
  0xD929D979L, 0x862E8691L, 0xD1ACD187L, 0xF415F44AL,
  0x8D598D15L, 0xD6A8D682L, 0xB90AB9BCL, 0x429E420DL,
  0xF66EF6C1L, 0x2F472FB8L, 0xDDDFDD06L, 0x23342339L,
  0xCC35CC62L, 0xF16AF1C4L, 0xC1CFC112L, 0x85DC85EBL,
  0x8F228F9EL, 0x71C971A1L, 0x90C090F0L, 0xAA9BAA53L,
  0x018901F1L, 0x8BD48BE1L, 0x4EED4E8CL, 0x8EAB8E6FL,
  0xAB12ABA2L, 0x6FA26F3EL, 0xE60DE654L, 0xDB52DBF2L,
  0x92BB927BL, 0xB702B7B6L, 0x692F69CAL, 0x39A939D9L,
  0xD3D7D30CL, 0xA761A723L, 0xA21EA2ADL, 0xC3B4C399L,
  0x6C506C44L, 0x07040705L, 0x04F6047FL, 0x27C22746L,
  0xAC16ACA7L, 0xD025D076L, 0x50865013L, 0xDC56DCF7L,
  0x8455841AL, 0xE109E151L, 0x7ABE7A25L, 0x139113EFL
};

static const unsigned long crypto_twofish_mds3[256] =
{
  0xD939A9D9L, 0x90176790L, 0x719CB371L, 0xD2A6E8D2L,
  0x05070405L, 0x9852FD98L, 0x6580A365L, 0xDFE476DFL,
  0x08459A08L, 0x024B9202L, 0xA0E080A0L, 0x665A7866L,
  0xDDAFE4DDL, 0xB06ADDB0L, 0xBF63D1BFL, 0x362A3836L,
  0x54E60D54L, 0x4320C643L, 0x62CC3562L, 0xBEF298BEL,
  0x1E12181EL, 0x24EBF724L, 0xD7A1ECD7L, 0x77416C77L,
  0xBD2843BDL, 0x32BC7532L, 0xD47B37D4L, 0x9B88269BL,
  0x700DFA70L, 0xF94413F9L, 0xB1FB94B1L, 0x5A7E485AL,
  0x7A03F27AL, 0xE48CD0E4L, 0x47B68B47L, 0x3C24303CL,
  0xA5E784A5L, 0x416B5441L, 0x06DDDF06L, 0xC56023C5L,
  0x45FD1945L, 0xA33A5BA3L, 0x68C23D68L, 0x158D5915L,
  0x21ECF321L, 0x3166AE31L, 0x3E6FA23EL, 0x16578216L,
  0x95106395L, 0x5BEF015BL, 0x4DB8834DL, 0x91862E91L,
  0xB56DD9B5L, 0x1F83511FL, 0x53AA9B53L, 0x635D7C63L,
  0x3B68A63BL, 0x3FFEEB3FL, 0xD630A5D6L, 0x257ABE25L,
  0xA7AC16A7L, 0x0F090C0FL, 0x35F0E335L, 0x23A76123L,
  0xF090C0F0L, 0xAFE98CAFL, 0x809D3A80L, 0x925CF592L,
  0x810C7381L, 0x27312C27L, 0x76D02576L, 0xE7560BE7L,
  0x7B92BB7BL, 0xE9CE4EE9L, 0xF10189F1L, 0x9F1E6B9FL,
  0xA93453A9L, 0xC4F16AC4L, 0x99C3B499L, 0x975BF197L,
  0x8347E183L, 0x6B18E66BL, 0xC822BDC8L, 0x0E98450EL,
  0x6E1FE26EL, 0xC9B3F4C9L, 0x2F74B62FL, 0xCBF866CBL,
  0xFF99CCFFL, 0xEA1495EAL, 0xED5803EDL, 0xF7DC56F7L,
  0xE18BD4E1L, 0x1B151C1BL, 0xADA21EADL, 0x0CD3D70CL,
  0x2BE2FB2BL, 0x1DC8C31DL, 0x195E8E19L, 0xC22CB5C2L,
  0x8949E989L, 0x12C1CF12L, 0x7E95BF7EL, 0x207DBA20L,
  0x6411EA64L, 0x840B7784L, 0x6DC5396DL, 0x6A89AF6AL,
  0xD17C33D1L, 0xA171C9A1L, 0xCEFF62CEL, 0x37BB7137L,
  0xFB0F81FBL, 0x3DB5793DL, 0x51E10951L, 0xDC3EADDCL,
  0x2D3F242DL, 0xA476CDA4L, 0x9D55F99DL, 0xEE82D8EEL,
  0x8640E586L, 0xAE78C5AEL, 0xCD25B9CDL, 0x04964D04L,
  0x55774455L, 0x0A0E080AL, 0x13508613L, 0x30F7E730L,
  0xD337A1D3L, 0x40FA1D40L, 0x3461AA34L, 0x8C4EED8CL,
  0xB3B006B3L, 0x6C54706CL, 0x2A73B22AL, 0x523BD252L,
  0x0B9F410BL, 0x8B027B8BL, 0x88D8A088L, 0x4FF3114FL,
  0x67CB3167L, 0x4627C246L, 0xC06727C0L, 0xB4FC90B4L,
  0x28382028L, 0x7F04F67FL, 0x78486078L, 0x2EE5FF2EL,
  0x074C9607L, 0x4B655C4BL, 0xC72BB1C7L, 0x6F8EAB6FL,
  0x0D429E0DL, 0xBBF59CBBL, 0xF2DB52F2L, 0xF34A1BF3L,
  0xA63D5FA6L, 0x59A49359L, 0xBCB90ABCL, 0x3AF9EF3AL,
  0xEF1391EFL, 0xFE0885FEL, 0x01914901L, 0x6116EE61L,
  0x7CDE2D7CL, 0xB2214FB2L, 0x42B18F42L, 0xDB723BDBL,
  0xB82F47B8L, 0x48BF8748L, 0x2CAE6D2CL, 0xE3C046E3L,
  0x573CD657L, 0x859A3E85L, 0x29A96929L, 0x7D4F647DL,
  0x94812A94L, 0x492ECE49L, 0x17C6CB17L, 0xCA692FCAL,
  0xC3BDFCC3L, 0x5CA3975CL, 0x5EE8055EL, 0xD0ED7AD0L,
  0x87D1AC87L, 0x8E057F8EL, 0xBA64D5BAL, 0xA8A51AA8L,
  0xB7264BB7L, 0xB9BE0EB9L, 0x6087A760L, 0xF8D55AF8L,
  0x22362822L, 0x111B1411L, 0xDE753FDEL, 0x79D92979L,
  0xAAEE88AAL, 0x332D3C33L, 0x5F794C5FL, 0xB6B702B6L,
  0x96CAB896L, 0x5835DA58L, 0x9CC4B09CL, 0xFC4317FCL,
  0x1A84551AL, 0xF64D1FF6L, 0x1C598A1CL, 0x38B27D38L,
  0xAC3357ACL, 0x18CFC718L, 0xF4068DF4L, 0x69537469L,
  0x749BB774L, 0xF597C4F5L, 0x56AD9F56L, 0xDAE372DAL,
  0xD5EA7ED5L, 0x4AF4154AL, 0x9E8F229EL, 0xA2AB12A2L,
  0x4E62584EL, 0xE85F07E8L, 0xE51D99E5L, 0x39233439L,
  0xC1F66EC1L, 0x446C5044L, 0x5D32DE5DL, 0x72466872L,
  0x26A06526L, 0x93CDBC93L, 0x03DADB03L, 0xC6BAF8C6L,
  0xFA9EC8FAL, 0x82D6A882L, 0xCF6E2BCFL, 0x50704050L,
  0xEB85DCEBL, 0x750AFE75L, 0x8A93328AL, 0x8DDFA48DL,
  0x4C29CA4CL, 0x141C1014L, 0x73D72173L, 0xCCB4F0CCL,
  0x09D4D309L, 0x108A5D10L, 0xE2510FE2L, 0x00000000L,
  0x9A196F9AL, 0xE01A9DE0L, 0x8F94368FL, 0xE6C742E6L,
  0xecc94aecL, 0xfdd25efdL, 0xab7fc1abL, 0xd8a8e0d8L
};

/*----*/

static const unsigned long crypto_sha_sbox[64] =
{
  0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L,
  0x3956C25BL, 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L,
  0xD807AA98L, 0x12835B01L, 0x243185BEL, 0x550C7DC3L,
  0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, 0xC19BF174L,
  0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
  0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL,
  0x983E5152L, 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L,
  0xC6E00BF3L, 0xD5A79147L, 0x06CA6351L, 0x14292967L,
  0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, 0x53380D13L,
  0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
  0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L,
  0xD192E819L, 0xD6990624L, 0xF40E3585L, 0x106AA070L,
  0x19A4C116L, 0x1E376C08L, 0x2748774CL, 0x34B0BCB5L,
  0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, 0x682E6FF3L,
  0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
  0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
};

/*============================================================================*/
/*              C  R  Y  P  T  O   -   F  U  N  C  T  I  O  N  S              */
/*============================================================================*/

/*-----------------*/
/*  TANDEM CIPHER  */
/*-----------------*/
                                                                   /* Set Key */
void crypto_tandem_setup (struct crypto_tandem_state *state, \
                          const unsigned long key[8])
{                                    /* ARM: 42330 Clocks = 203.5uS @ 208 MHz */
  unsigned long k[8];
  unsigned char c;

  /* Setup AES */
  crypto_sha_setup (&(state->sha));
  crypto_sha_add (&(state->sha), (const unsigned char *)key, 32);
  c = 0x00;
  crypto_sha_add (&(state->sha), &c, 1);
  crypto_sha_final (&(state->sha), (unsigned char *)k, 32);
  crypto_aes_setup (state->aes_xkey, k);

  /* Setup Twofish */
  crypto_sha_setup (&(state->sha));
  crypto_sha_add (&(state->sha), (const unsigned char *)key, 32);
  c = 0x01;
  crypto_sha_add (&(state->sha), &c, 1);
  crypto_sha_final (&(state->sha), (unsigned char *)k, 32);
  crypto_twofish_setup (&(state->twofish), k);
}

/*----*/
                                                             /* Encrypt Block */
void crypto_tandem_encrypt (const struct crypto_tandem_state *state, \
                            const unsigned long din[4], unsigned long dout[4])
{                                      /* ARM: 3710 Clocks = 17.8uS @ 208 MHz */
  const unsigned long *p;
  unsigned long a[4];

  /* Double encrypt */
  crypto_aes_encrypt (state->aes_xkey, din, dout);
  crypto_twofish_encrypt (&(state->twofish), din, a);
  p = a;
  *dout++ ^= *p++;
  *dout++ ^= *p++;
  *dout++ ^= *p++;
  *dout   ^= *p;
}

/*----------------------------------------------------------------------------*/

/*------------*/
/*  RIJNDAEL  */
/*------------*/
                                                                   /* Set Key */
void crypto_aes_setup (unsigned long xkey[60], const unsigned long key[8])
{                                       /* ARM: 535 Clocks = 2.57uS @ 208 MHz */
  const unsigned long *p;
  unsigned long a,b;
  unsigned char i;

  p = xkey;
  *xkey++ = *key++;
  *xkey++ = *key++;
  *xkey++ = *key++;
  *xkey++ = *key++;
  *xkey++ = *key++;
  *xkey++ = *key++;
  *xkey++ = *key++;
  a = *key;
  b = 1;
  i = 6;
  while (42)
  {
    *xkey++ = a;
    a = *p++                                                                \
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a      )]) << 24) \
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a >>  8)])      ) \
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a >> 16)]) <<  8) \
      ^ ((unsigned long)(crypto_aes_sbox0[               (a >> 24)]) << 16) \
      ^ b;
    *xkey++ = a;
    a = *p++ ^ a;
    *xkey++ = a;
    a = *p++ ^ a;
    *xkey++ = a;
    a = *p++ ^ a;
    *xkey++ = a;
    if (!i)
      break;
    i--;
    a = *p++
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a      )])      ) \
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a >>  8)]) <<  8) \
      ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(a >> 16)]) << 16) \
      ^ ((unsigned long)(crypto_aes_sbox0[               (a >> 24)]) << 24);
    *xkey++ = a;
    a = *p++ ^ a;
    *xkey++ = a;
    a = *p++ ^ a;
    *xkey++ = a;
    a = *p++ ^ a;
    b <<= 1;
  }
}

/*----*/
                                                             /* Encrypt Block */
void crypto_aes_encrypt (const unsigned long xkey[60], \
                         const unsigned long din[4], unsigned long dout[4])
{                                      /* ARM: 1077 Clocks = 5.63uS @ 208 MHz */
  unsigned long a0,a1,a2,a3,b0,b1,b2,b3;
  unsigned char i;

  a0 = *din++ ^ *xkey++;
  a1 = *din++ ^ *xkey++;
  a2 = *din++ ^ *xkey++;
  a3 = *din   ^ *xkey++;
  i = 6;
  while (42)
  {
    b0 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(a0      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(a1 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(a2 >> 16)] \
                 ^ crypto_aes_sbox4[               (a3 >> 24)];
    b1 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(a1      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(a2 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(a3 >> 16)] \
                 ^ crypto_aes_sbox4[               (a0 >> 24)];
    b2 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(a2      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(a3 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(a0 >> 16)] \
                 ^ crypto_aes_sbox4[               (a1 >> 24)];
    b3 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(a3      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(a0 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(a1 >> 16)] \
                 ^ crypto_aes_sbox4[               (a2 >> 24)];
    if (!i)
      break;
    i--;
    a0 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(b0      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(b1 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(b2 >> 16)] \
                 ^ crypto_aes_sbox4[               (b3 >> 24)];
    a1 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(b1      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(b2 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(b3 >> 16)] \
                 ^ crypto_aes_sbox4[               (b0 >> 24)];
    a2 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(b2      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(b3 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(b0 >> 16)] \
                 ^ crypto_aes_sbox4[               (b1 >> 24)];
    a3 = *xkey++ ^ crypto_aes_sbox1[(unsigned char)(b3      )] \
                 ^ crypto_aes_sbox2[(unsigned char)(b0 >>  8)] \
                 ^ crypto_aes_sbox3[(unsigned char)(b1 >> 16)] \
                 ^ crypto_aes_sbox4[               (b2 >> 24)];
  }
  a0 = *xkey++
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b0      )])      ) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b1 >>  8)]) <<  8) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b2 >> 16)]) << 16) \
     ^ ((unsigned long)(crypto_aes_sbox0[               (b3 >> 24)]) << 24);
  a1 = *xkey++
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b1      )])      ) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b2 >>  8)]) <<  8) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b3 >> 16)]) << 16) \
     ^ ((unsigned long)(crypto_aes_sbox0[               (b0 >> 24)]) << 24);
  a2 = *xkey++
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b2      )])      ) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b3 >>  8)]) <<  8) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b0 >> 16)]) << 16) \
     ^ ((unsigned long)(crypto_aes_sbox0[               (b1 >> 24)]) << 24);
  a3 = *xkey
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b3      )])      ) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b0 >>  8)]) <<  8) \
     ^ ((unsigned long)(crypto_aes_sbox0[(unsigned char)(b1 >> 16)]) << 16) \
     ^ ((unsigned long)(crypto_aes_sbox0[               (b2 >> 24)]) << 24);
  *dout++ = a0;
  *dout++ = a1;
  *dout++ = a2;
  *dout   = a3;
}

/*-----------*/
/*  TWOFISH  */
/*-----------*/
                                                                   /* Set Key */
void crypto_twofish_setup (struct crypto_twofish_state *state, \
                           const unsigned long key[8])
{                                   /* ARM: 29870 Clocks = 143.62uS @ 208 MHz */
  unsigned long a,b,x,y,z,*p,ekey[4],okey[4],skey[4];
  unsigned char c,i,j,k;
  unsigned short n;

  /* Sbox keys */
  for (i=0; i<4; i++)
  {
    x =*key++;
    y =*key++;
    z = 0L;
    for (j=0; j<2; j++)
    {
      z ^= j ? x : y;
      for (k=0; k<4; k++)
      {
        c = (unsigned char)(z >> 24);
        a = ((c << 1) & 0xFF) ^ ((c & 0x80) ? 0x4D : 0);
        b = ((c >> 1) & 0x7F) ^ ((c & 0x01) ? 0xA6 : 0) ^ a;
        z = (z << 8) ^ (b << 24) ^ (a << 16) ^ (b << 8) ^ c;
      }
    }
    ekey[i] = x;
    okey[i] = y;
    skey[i] = z;
  }

  /* Round subkeys */
  x = 0L;
  p = state->xkey;
  for (i=0; i<20; i++)
  {
    /* Calc A */
    a = ekey[3]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (x >> 24)]) << 24);
    a = ekey[2]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(a      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(a >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(a >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox0[               (a >> 24)]) << 24);
    a = ekey[1]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(a      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(a >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(a >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (a >> 24)]) << 24);
    a = ekey[0]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(a      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(a >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(a >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (a >> 24)]) << 24);
    a = crypto_twofish_mds0[(unsigned char)(a      )] \
      ^ crypto_twofish_mds1[(unsigned char)(a >>  8)] \
      ^ crypto_twofish_mds2[(unsigned char)(a >> 16)] \
      ^ crypto_twofish_mds3[               (a >> 24)];
    x += 0x01010101L;
    /* Calc B */
    b = okey[3]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (x >> 24)]) << 24);
    b = okey[2]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(b      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(b >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(b >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox0[               (b >> 24)]) << 24);
    b = okey[1]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(b      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(b >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(b >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (b >> 24)]) << 24);
    b = okey[0]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(b      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(b >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(b >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (b >> 24)]) << 24);
    b = crypto_twofish_mds0[(unsigned char)(b      )] \
      ^ crypto_twofish_mds1[(unsigned char)(b >>  8)] \
      ^ crypto_twofish_mds2[(unsigned char)(b >> 16)] \
      ^ crypto_twofish_mds3[               (b >> 24)];
    x += 0x01010101L;
    /* Store subkey */
    b = (b << 8) | (b >> 24);
    a += b;
    *p++ = a;
    a += b;
    a = (a << 9) | (a >> 23);
    *p++ = a;
  }

  /* Build sbox */
  p = state->sbox;
  for (n=0; n<256; n++)
  {
    x = n;
    x = (x << 24) | (x << 16) | (x << 8) | x;
    x = skey[0]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (x >> 24)]) << 24);
    x = skey[1]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox0[               (x >> 24)]) << 24);
    x = skey[2]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (x >> 24)]) << 24);
    x = skey[3]                                                               \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x      )])      ) \
    ^ ((unsigned long)(crypto_twofish_sbox0[(unsigned char)(x >>  8)]) <<  8) \
    ^ ((unsigned long)(crypto_twofish_sbox1[(unsigned char)(x >> 16)]) << 16) \
    ^ ((unsigned long)(crypto_twofish_sbox1[               (x >> 24)]) << 24);
    *p++ = crypto_twofish_mds0[(unsigned char)(x      )];
    *p++ = crypto_twofish_mds1[(unsigned char)(x >>  8)];
    *p++ = crypto_twofish_mds2[(unsigned char)(x >> 16)];
    *p++ = crypto_twofish_mds3[               (x >> 24)];
  }
}

/*----*/
                                                             /* Encrypt Block */
void crypto_twofish_encrypt (const struct crypto_twofish_state *state, \
                             const unsigned long din[4], unsigned long dout[4])
{                                      /* ARM: 1020 Clocks = 4.92uS @ 208 MHz */
  unsigned long t0,t1,x0,x1,x2,x3;
  const unsigned long *xkey;
  unsigned char i;

  xkey = state->xkey;
  x0 = *din++ ^ *xkey++;
  x1 = *din++ ^ *xkey++;
  x2 = *din++ ^ *xkey++;
  x3 = *din   ^ *xkey;
  xkey += 5;
  for (i=0; i<8; i++)
  {
    t0 = state->sbox[((x0 <<  2) & 0x000003FCL)    ] \
       ^ state->sbox[((x0 >>  6) & 0x000003FCL) + 1] \
       ^ state->sbox[((x0 >> 14) & 0x000003FCL) + 2] \
       ^ state->sbox[((x0 >> 22) & 0x000003FCL) + 3];
    t1 = state->sbox[((x1 >> 22) & 0x000003FCL)    ] \
       ^ state->sbox[((x1 <<  2) & 0x000003FCL) + 1] \
       ^ state->sbox[((x1 >>  6) & 0x000003FCL) + 2] \
       ^ state->sbox[((x1 >> 14) & 0x000003FCL) + 3];
    t0 += t1;
    x2 ^= t0 + *xkey++;
    x2 = (x2 >> 1) | (x2 << 31);
    x3 = (x3 << 1) | (x3 >> 31);
    x3 ^= t0 + t1 + *xkey++;
    t0 = state->sbox[((x2 <<  2) & 0x000003FCL)    ] \
       ^ state->sbox[((x2 >>  6) & 0x000003FCL) + 1] \
       ^ state->sbox[((x2 >> 14) & 0x000003FCL) + 2] \
       ^ state->sbox[((x2 >> 22) & 0x000003FCL) + 3];
    t1 = state->sbox[((x3 >> 22) & 0x000003FCL)    ] \
       ^ state->sbox[((x3 <<  2) & 0x000003FCL) + 1] \
       ^ state->sbox[((x3 >>  6) & 0x000003FCL) + 2] \
       ^ state->sbox[((x3 >> 14) & 0x000003FCL) + 3];
    t0 += t1;
    x0 ^= t0 + *xkey++;
    x0 = (x0 >> 1) | (x0 << 31);
    x1 = (x1 << 1) | (x1 >> 31);
    x1 ^= t0 + t1 + *xkey++;
  }
  xkey -= 36;
  *dout++ = x2 ^ *xkey++;
  *dout++ = x3 ^ *xkey++;
  *dout++ = x0 ^ *xkey++;
  *dout   = x1 ^ *xkey;
}

/*----------------------------------------------------------------------------*/

/*-----------*/
/*  SHA-256  */
/*-----------*/

void crypto_sha_setup (struct crypto_sha_state *state)            /* Init SHA */
{
  unsigned long *p;

  /* Init state */
  p = state->hash;
  *p++ = 0x6A09E667L;
  *p++ = 0xBB67AE85L;
  *p++ = 0x3C6EF372L;
  *p++ = 0xA54FF53AL;
  *p++ = 0x510E527FL;
  *p++ = 0x9B05688CL;
  *p++ = 0x1F83D9ABL;
  *p   = 0x5BE0CD19L;
  state->len = 0L;
}

/*----*/
                                                               /* Import Data */
void crypto_sha_add (struct crypto_sha_state *state, const unsigned char *din, \
                     unsigned long dlen)
{                /* ARM: 2.2MB/Sec, 64 Byte in 5690 Clocks = 27.3uS @ 208 MHz */
  unsigned char i,*p;

  /* Import data */
  p = (unsigned char *)(state->buf);
  i = (unsigned char)(state->len & 0x3F);
  state->len += dlen;
  while (dlen--)
  {
    p[i^3] = *din++;
    i++;
    if (i == 64)
    {
      crypto_sha__compress (state);
      i = 0;
    }
  }
}

/*----*/
                                                               /* Calc Result */
void crypto_sha_final (struct crypto_sha_state *state, unsigned char *dout, \
                       unsigned char dlen)
{
  unsigned char c,i,*p;

  /* Final block */
  p = (unsigned char *)(state->buf);
  i = (unsigned char)(state->len & 0x3F);
  c = 0x80;
  do
  {
    p[i^3] = c;
    c = 0;
    i++;
    if (i == 64)
    {
      crypto_sha__compress (state);
      i = 0;
    }
  } while (i != 56);
  state->buf[14] = state->len >> 29;
  state->buf[15] = state->len << 3;
  crypto_sha__compress (state);

  /* Export hash */
  p = (unsigned char *)(state->hash);
  if (dlen > 32)
    dlen = 32;
  for (i=0; i<dlen; i++)
    *dout++ = p[i^3];
}

/*====*/
                                                            /* Compress Block */
static void crypto_sha__compress (struct crypto_sha_state *state)
{                                      /* ARM: 4680 Clocks = 22.5uS @ 208 MHz */
  unsigned long a,b,c,d,x,y,*p,h[8];
  const unsigned long *q;
  unsigned char i;

  /* Setup data */
  p = h;
  q = state->hash;
  for (i=0; i<8; i++)
    *p++ = *q++;
  p = state->buf + 16;
  for (i=0; i<48; i++)
  {
    a = *(p-2);
    b = *(p-7);
    c = *(p-15);
    d = *(p-16);
    a = ((a>>17)|(a<<15)) ^ ((a>>19)|(a<<13)) ^ (a>>10);
    c = ((c>>7)|(c<<25)) ^ ((c>>18)|(c<<14)) ^ (c>>3);
    *p++ = a + b + c + d;
  }

  /* Sha rounds */
  p = state->buf;
  q = crypto_sha_sbox;
  for (i=0; i<64; i++)
  {
    /* Calc X */
    a = h[4];
    b = h[5];
    c = h[6];
    d = h[7];
    b = (a & b) ^ (~a & c);
    a = ((a>>6)|(a<<26)) ^ ((a>>11)|(a<<21)) ^ ((a>>25)|(a<<7));
    x = a + b + d + *p++ + *q++;
    /* Calc Y */
    a = h[0];
    b = h[1];
    c = h[2];
    b = (a & b) ^ (a & c) ^ (b & c);
    a = ((a>>2)|(a<<30)) ^ ((a>>13)|(a<<19)) ^ ((a>>22)|(a<<10));
    y = a + b;
    /* Update */
    h[7] = h[6];
    h[6] = h[5];
    h[5] = h[4];
    h[4] = h[3] + x;
    h[3] = h[2];
    h[2] = h[1];
    h[1] = h[0];
    h[0] = x + y;
  }

  /* Update hash */
  p = state->hash;
  q = h;
  for (i=0; i<8; i++)
    *p++ += *q++;
}


/*** EOF ***/
